package com.lagou.netty.chapter01;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;

import java.net.InetSocketAddress;

/**
 * @author zjiajia
 * @date 2024/7/8 16:14
 */
public class HttpServer {
    public static void main(String[] args) {
        new HttpServer().start(8888);
    }

    public  void start(int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();


        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap
                    /**
                     * group 是配置 reactor 的模型，又三种模型方式 ：
                     *      1. 单线程模型
                     *      2. 多线程模型
                     *      3. 主从模型
                     *
                     *      // 单线程模型
                     *     EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1);
                     *     serverBootstrap.group(eventLoopGroup)
                     *
                     *     //  多线程模型
                     *     EventLoopGroup eventLoopGroup = new NioEventLoopGroup();     // 默认会创建 cpu核数 * 2 的线程数
                     *     serverBootstrap.group(eventLoopGroup)
                     *
                     *     // 主从模型
                     *     EventLoopGroup bossGroup = new NioEventLoopGroup();
                     *     NioEventLoopGroup workerGroup = new NioEventLoopGroup();
                     *     serverBootstrap.group(bossGroup,workerGroup);
                     *
                     */
                    .group(bossGroup,workerGroup)
                    /**
                     * 设置 IO 模型 ：
                     *      1. 一般来说使用 NIO
                     *      2. 也可以使用 BIO，那么这里就需要使用 IioServerSocketChannel
                     *      3. 在客户端，使用的应该 xxxSocketChannel
                     */
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    /**
                     * 设置 handler 的执行链，用来处理具体的业务逻辑
                     */
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    // 设置 http 编解码器
                                    .addLast("codec",new HttpServerCodec())
                                    // 设置 http content 压缩处理器
                                    .addLast("compressor",new HttpContentCompressor())
                                    // 设置 http 聚合消息处理
                                    .addLast("aggregator",new HttpObjectAggregator(65536))
                                    // 自定业务逻辑处理
                                    .addLast("handler",new HttpServerHandler());
                        }
                    })
                    .childOption(ChannelOption.SO_KEEPALIVE,true);

            ChannelFuture channelFuture = serverBootstrap.bind().sync();
            System.out.println("http server started. listening on " + port);
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}
